home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJSRC111.ZIP / go32 / exphdlr.c < prev    next >
C/C++ Source or Header  |  1993-11-27  |  36KB  |  1,311 lines

  1. /* This is file EXPHDLR.C */
  2. /*
  3. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
  16. /* Modified for DPMI Implement by H.Tsubakimoto */
  17. /* Merged DPMI with V1.09+ C. Sandmann sandmann@clio.rice.edu */
  18. /* History:66,55 */
  19.  
  20. #include <process.h>
  21. #include <stdio.h>
  22. #include <dos.h>
  23. #include <sys/stat.h>
  24. #include <time.h>
  25. #include <errno.h>
  26. #include <fcntl.h>
  27. #include <string.h>
  28. #include <dir.h>
  29. #include <ctype.h>
  30. #include <io.h>
  31.  
  32. #include "gotypes.h"
  33. #include "gdt.h"
  34. #include "idt.h"
  35. #include "tss.h"
  36. #include "utils.h"
  37. #include "paging.h"
  38. #include "npx.h"
  39. #include "mono.h"
  40. #include "vcpi.h"
  41. #include "graphics.h"
  42. #include "dpmi.h"
  43. #include "extdebug.h"
  44. #include "vcpi.h"
  45. #include "ustat.h"
  46. #include "dpmisim.h"
  47. #include "dalloc.h"
  48. #include "valloc.h"
  49. #include "control.h"
  50.  
  51. extern void do_faulting_finish_message(int);
  52.  
  53. void segfault(word32 v)
  54. {
  55.   if (!using_external_debugger || (tss_ptr == &ed_tss))
  56.   {
  57.     fprintf(stderr, "Segmentation violation in pointer 0x%08lx at %x:%lx\n", v-ARENA, tss_ptr->tss_cs, tss_ptr->tss_eip);
  58.     do_faulting_finish_message(0);
  59.   }
  60.   tss_ptr->tss_irqn = 14; /* make it a segfault */
  61.   tss_ptr->tss_cr2 = v;
  62. }
  63.  
  64. #define CHECK_SEGFAULT(p) { \
  65.   if (!page_is_valid(p)) \
  66.   { \
  67.     segfault(p); \
  68.     return 1; \
  69.   } \
  70. }
  71.  
  72. extern int debug_mode;
  73.  
  74. extern unsigned int cdecl _openfd[];
  75. extern word32 far *graphics_pt;
  76. extern int ctrl_break_hit;
  77.  
  78. extern int was_user_int;
  79. extern word16 vcpi_installed;           /* VCPI Installed flag */
  80. word16 new_pic;                         /* current IRQ0 Vector */
  81. char transfer_buffer[4096];             /* must be near ptr for small model */
  82. word32 transfer_linear;
  83.  
  84. int in_hardware_interrupt = 0;
  85.  
  86. word8 old_master_lo=0x08;
  87. word8 hard_master_lo=0x08, hard_master_hi=0x0f;
  88. word8 hard_slave_lo=0x70,  hard_slave_hi=0x77;
  89.  
  90. word32 user_dta;
  91. static struct REGPACK r;
  92. static int in_graphics_mode=0;
  93. int ctrl_c_causes_break=1;
  94.  
  95. static int i_10(void), i_21(void), i_31(void), i_33(void), generic_handler(void), i_21_44(void);
  96. static int turbo_assist(void);
  97.  
  98. static word32 flmerge(word32 rf, word32 tf)
  99. {
  100.   return (rf & 0xcff) | (tf & 0xfffff300L);
  101. }
  102.  
  103. void static set_controller(int v)
  104. {
  105. /*  disable();  */
  106.   outportb(0x20, 0x11);
  107.   outportb(0x21, v);
  108.   outportb(0x21, 4);
  109.   outportb(0x21, 1);
  110. /*  enable();  */
  111. }
  112.  
  113. static char cntrls_initted = 0;
  114. extern char vector_78h, vector_79h;
  115.  
  116. int find_empty_pic(void)
  117. {
  118.   static word8 try[] = { 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xf8, 0x68, 0x78 };
  119.   int i, j;
  120.   for (i=0; i<sizeof(try); i++)
  121.   {
  122.     char far * far * vec = (char far * far *)(0L+try[i]*4L);
  123.     for (j=1; j<8; j++)
  124.     {
  125.       if (vec[j] != vec[0])
  126.         goto not_empty;
  127.     }
  128. /*    printf("Empty = %d\n", try[i]); */
  129.     return try[i];
  130.     not_empty:;
  131.   }
  132.   return 0x78;
  133. }
  134.  
  135. extern int  far _ev_kbinter;            /* keyboard interrupt flag */
  136. extern void interrupt (* far _ev_oldkbint)(void);
  137. extern void interrupt _ev_keybdint(void);
  138.  
  139. word32 saved_interrupt_table[256];
  140.  
  141. void init_controllers(void)
  142. {
  143.   if(cntrls_initted) return;
  144.   cntrls_initted = 1;
  145.  
  146.   movedata(0, 0, _DS, FP_OFF(saved_interrupt_table), 256*4);
  147.  
  148.   disable();
  149.  
  150.   if (vcpi_installed)
  151.   {
  152.     old_master_lo = vcpi_get_pic();
  153.     hard_slave_lo = vcpi_get_secpic();
  154. /*    printf("VCPI pics were m=%d s=%d\n", old_master_lo, hard_slave_lo); */
  155.     hard_slave_hi = hard_slave_lo + 7;
  156.   }
  157.   else if(!use_DPMI)
  158.   {
  159.     old_master_lo = 0x08;
  160.     hard_slave_lo = 0x70;
  161.     hard_slave_hi = 0x77;
  162.   }
  163.  
  164.   _ev_kbinter = 1;
  165.   _ev_oldkbint = getvect(8+1);     /* this is *NOT* old_master_lo - required */
  166.   setvect(8+1,_ev_keybdint);       /* so DV/X will work (it redirects) */
  167.  
  168.   if(use_DPMI)
  169.   {
  170.     enable();
  171.     return;
  172.   }
  173.  
  174.   if (old_master_lo == 0x08)
  175.   {
  176.     hard_master_lo = find_empty_pic();
  177.     if (vcpi_installed)
  178.       vcpi_set_pics(hard_master_lo, hard_slave_lo);
  179.     set_controller(hard_master_lo);
  180.     movedata(0, 0x08*4, 0, hard_master_lo*4, 0x08*4);
  181.   }
  182.   else
  183.   {
  184.     hard_master_lo = old_master_lo;
  185.   }
  186.   hard_master_hi = hard_master_lo + 7;
  187.  
  188.   enable();
  189.   vector_78h = hard_master_lo;
  190.   vector_79h = hard_master_lo + 1;
  191. }
  192.  
  193. void uninit_controllers(void)
  194. {
  195.   if(!cntrls_initted) return;
  196.   cntrls_initted = 0;
  197.   disable();
  198.  
  199.   movedata(_DS, FP_OFF(saved_interrupt_table), 0, 0, 256*4);
  200.  
  201.   if (old_master_lo == 0x08 && !use_DPMI)
  202.   {
  203.     if (vcpi_installed)
  204.       vcpi_set_pics(0x08, hard_slave_lo);
  205.     set_controller(0x08);
  206.   }
  207.   setvect(8+1,_ev_oldkbint);  /* not old_master_lo for XDV */
  208.   enable();
  209. }
  210.  
  211. static DPMIaddress exceptions[17];
  212. static DPMIaddress interrupt10;
  213. static DPMIaddress interrupt21;
  214. static DPMIaddress interrupt33;
  215. static DPMIaddress interrupt75;
  216.  
  217. void setDPMIvector(void)
  218. {
  219.   int i;
  220.   for (i = 0; i < sizeof(exceptions) / sizeof(*exceptions); ++i) {
  221.     DPMIehandler(i, &exceptions[i]);
  222.     DPMIchangeException(i, &exceptions[i]);
  223.   }
  224.   DPMIhandler(0x10, &interrupt10);
  225.   DPMIchangeInterrupt(0x10, &interrupt10);
  226.   DPMIhandler(0x21, &interrupt21);
  227.   DPMIchangeInterrupt(0x21, &interrupt21);
  228.   DPMIhandler(0x33, &interrupt33);
  229.   DPMIchangeInterrupt(0x33, &interrupt33);
  230.   DPMIhandlerNPX(&interrupt75);
  231.   DPMIchangeInterrupt(0x75, &interrupt75);
  232. }
  233.  
  234. void restoreDPMIvector(void)
  235. {
  236.   int i;
  237.   for (i = 0; i < sizeof(exceptions) / sizeof(*exceptions); ++i)
  238.     DPMIchangeException(i, &exceptions[i]);
  239.   DPMIchangeInterrupt(0x10, &interrupt10);
  240.   DPMIchangeInterrupt(0x21, &interrupt21);
  241.   DPMIchangeInterrupt(0x33, &interrupt33);
  242.   DPMIchangeInterrupt(0x75, &interrupt75);
  243. }
  244.  
  245. void tss2reg(struct REGPACK *r)
  246. {
  247.   r->r_ax = (word16)(tss_ptr->tss_eax);
  248.   r->r_bx = (word16)(tss_ptr->tss_ebx);
  249.   r->r_cx = (word16)(tss_ptr->tss_ecx);
  250.   r->r_dx = (word16)(tss_ptr->tss_edx);
  251.   r->r_si = (word16)(tss_ptr->tss_esi);
  252.   r->r_di = (word16)(tss_ptr->tss_edi);
  253.   r->r_flags = (word16)(tss_ptr->tss_eflags);
  254.   r->r_ds = r->r_es = _DS;
  255. }
  256.  
  257. void reg2tss(struct REGPACK *r)
  258. {
  259.   tss_ptr->tss_eax = r->r_ax;
  260.   tss_ptr->tss_ebx = r->r_bx;
  261.   tss_ptr->tss_ecx = r->r_cx;
  262.   tss_ptr->tss_edx = r->r_dx;
  263.   tss_ptr->tss_esi = r->r_si;
  264.   tss_ptr->tss_edi = r->r_di;
  265.   tss_ptr->tss_eflags = flmerge(r->r_flags, tss_ptr->tss_eflags);
  266. }
  267.  
  268. extern int ctrl_c_flag;
  269.  
  270. int double_fault(void)
  271. {
  272.   fprintf(stderr, "double fault!\n");
  273.   exit(1);
  274.   return 1;
  275. }
  276.  
  277. int check_nonpresent_387(void )
  278. {
  279.   if (!using_external_debugger)
  280.   {
  281.     fprintf(stderr, "Fatal!  Application attempted to use not-present 80387!\n");
  282.     fprintf(stderr, "Floating point opcode at virtual address 0x%08lx\n", tss_ptr->tss_eip);
  283.   }
  284.   return 1;
  285. }
  286.  
  287. int unsupported_int()
  288. {
  289.   if (!debug_mode)
  290.     fprintf(stderr, "Unsupported INT 0x%02x\n", tss_ptr->tss_irqn);
  291.   return 1;
  292. }
  293.  
  294. #define U unsupported_int
  295. typedef int (*FUNC)(void);
  296. static FUNC exception_handler_list[] = {
  297.   U, U, U, U, U, U, U,
  298.   /* 07 */ check_nonpresent_387,
  299.   /* 08 */ double_fault,
  300.   U, U, U, U, U,
  301.   /* 0e */ page_in,
  302.   U,
  303.   /* 10 */ i_10,        /* Video Interrupt */
  304.   /* 11 */ generic_handler,    /* Equipment detection */
  305.   /* 12 */ generic_handler,    /* Get memory size (outdated) */
  306.   U,
  307.   /* 14 */ generic_handler,    /* Serial communication */
  308.   /* 15 */ generic_handler,    /* Lots of strange things */
  309.   /* 16 */ generic_handler,    /* Keyboard */
  310.   /* 17 */ generic_handler,    /* Parallel printer */
  311.   U, U,
  312.   /* 1a */ generic_handler,    /* Get/set system time */
  313.   U, U, U, U, U, U,
  314.   /* 21 */ i_21,        /* DOS Services */
  315.   U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
  316.   /* 31 */ i_31,        /* DPMIsim */
  317.   U,
  318.   /* 33 */ i_33            /* Mouse */
  319. };
  320. #undef U
  321. #define NUM_EXCEPTIONS    (sizeof(exception_handler_list)/sizeof(exception_handler_list[0]))
  322.  
  323. exception_handler(void)
  324. {
  325.   int i;
  326.   if (topline_info)
  327.   {
  328.     char buf[20];
  329.     if (tss_ptr->tss_irqn == 14)
  330.       sprintf(buf, "0x%08lx", tss_ptr->tss_cr2 - ARENA);
  331.     else
  332.       sprintf(buf, "0x%08lx", tss_ptr->tss_eip);
  333.     for (i=0; buf[i]; i++)
  334.       poke(screen_seg, i*2+80, buf[i] | 0x0600);
  335.   }
  336.   i = tss_ptr->tss_irqn;
  337. /*  printf("i=%#02x\n", i); */
  338.   if (((i >= hard_slave_lo)  && (i <= hard_slave_hi)
  339.        && (i != hard_slave_lo + 5))
  340.       || ((i >= hard_master_lo) && (i <= hard_master_hi)))
  341.   {
  342.     in_hardware_interrupt = 1;
  343.     intr(i, &r);
  344.     in_hardware_interrupt = 0;
  345.     if (ctrl_break_hit)
  346.       return 1;
  347.     if (i == hard_master_lo + 1)
  348.     {
  349.       if (ctrl_c_causes_break)
  350.       {
  351.         r.r_ax = 0x0100;
  352.         intr(0x16, &r);
  353.         if (!(r.r_flags & 0x40) && (r.r_ax == 0x2e03))
  354.         {
  355.           _AH = 0;
  356.           geninterrupt(0x16);
  357.           ctrl_c_flag = 1;
  358.         }
  359.       }
  360.     }
  361.     if (ctrl_c_flag)
  362.     {
  363.       ctrl_c_flag = 0;
  364.       if (ctrl_c_causes_break)
  365.         return 1;
  366.     }
  367.     return 0;
  368.   }
  369.   if (i < NUM_EXCEPTIONS)
  370.     return (exception_handler_list[i])();
  371.   else
  372.     return 1;
  373. }
  374.  
  375. void retrieve_string(word32 v, char *transfer_buffer, char tchar)
  376. {
  377.   int i;
  378.   if (!use_DPMI) {
  379. #if 0
  380.     for (i=0; i<4096; i++)
  381.     {
  382.       c = peek8(v);
  383.       v++;
  384.       transfer_buffer[i] = c;
  385.       if (c == tchar)
  386.         break;
  387.     }
  388. #else
  389.     memscan32(v, transfer_buffer, tchar);
  390. #endif
  391.     return;
  392.   } else {
  393.     i = Pmemscan(tss_ptr->tss_ds, v, tchar, 4096);
  394.     if (i == 0) i = 4096;
  395.     Pmemget(tss_ptr->tss_ds, v, transfer_buffer, i);
  396.     return;
  397.   }
  398. }
  399.  
  400. generic_handler(void)
  401. {
  402.   tss2reg(&r);
  403.   intr(tss_ptr->tss_irqn, &r);
  404.   reg2tss(&r);
  405.   return 0;
  406. }
  407.  
  408. i_10(void)
  409. {
  410.   word32 v;
  411.   word16 i, j;
  412.  
  413. /* CB changes */
  414. /* OLD:
  415.  * switch((word16)(tss_ptr->tss_eax) & 0xFF00) {
  416.  *   case 0xFD00:
  417.  *     graphics_pageflip();
  418.  *     return 0;
  419.  *   case 0xFE00:
  420.  *     graphics_inquiry();
  421.  *     return 0;
  422.  *   case 0xFF00:
  423.  *     graphics_mode((word16)(tss_ptr->tss_eax) & 0xff);
  424.  *     in_graphics_mode = (peekb(0x40, 0x49) > 7);
  425.  *     return 0;
  426.  * }
  427.  */
  428.   if(((word16)tss_ptr->tss_eax & 0xff00) >= gr_assist_func_start) {
  429.     graphics_assist();
  430.     in_graphics_mode = (peekb(0x40, 0x49) > 7);
  431.     return 0;
  432.   }
  433. /* end CB changes */
  434.   tss2reg(&r);
  435.  
  436.   i = (word16)tss_ptr->tss_eax; /* int10 function 0x11 subfunctions 0 & 0x10 */
  437.   if(i==0x1100 || i==0x1110)
  438.   { /* user-defined text characters */
  439.     v = tss_ptr->tss_edx + ARENA; /* bh*cx bytes starting at (ds:dx) */
  440.     CHECK_SEGFAULT(v);
  441.     j = ((tss_ptr->tss_ebx >> 8) & 0xff) * ((word16)tss_ptr->tss_ecx);
  442.     memget(v, transfer_buffer, j);
  443.     r.r_dx = FP_OFF(transfer_buffer);
  444.     r.r_ds = _DS;
  445.   }
  446.  
  447.   intr(0x10, &r);
  448.   reg2tss(&r);
  449.   tss_ptr->tss_ebp = r.r_es * 16L + r.r_bp + 0xe0000000L;
  450.   return 0;
  451. }
  452.  
  453. #include "eventque.h"
  454.  
  455. #define  MSDRAW_STACK  128              /* stack size for mouse callback */
  456.  
  457. static word32  mousedraw_func32;        /* 32-bit mouse cursor drawing function */
  458. static word32  mousedraw_contaddr;      /* jump to this address after mouse draw */
  459. static char    mousedraw_active;        /* set while drawing mouse cursor */
  460. EventQueue    *event_queue = NULL;      /* event queue */
  461. typedef int far (*FFUNC)(void);
  462. static FFUNC   mousedraw_callback = 0;    /* DPMI real mode callback to prot */
  463.  
  464. static void mousedraw_hook(void)
  465. {
  466.   disable();
  467.   if(!mousedraw_active)
  468.   {
  469.     mousedraw_active = 1;
  470.     if(use_DPMI)
  471.     {
  472.       mousedraw_callback();
  473.       mousedraw_active = 0;
  474.     }
  475.     else
  476.     {
  477.       mousedraw_contaddr = a_tss.tss_eip;
  478.       a_tss.tss_eip = mousedraw_func32;
  479.     }
  480.   }
  481.   enable();
  482. }
  483.  
  484. i_33(void)
  485. {
  486.   void (*msdrawfun)(void);
  487.   int  queuesize;
  488.  
  489.   if(tss_ptr->tss_eax == 0x00ff) {
  490.     if(event_queue != NULL) {
  491.       EventQueueDeInit();
  492.       event_queue = NULL;
  493.     }
  494.     if((queuesize = (int)tss_ptr->tss_ebx) > 0) {
  495.       mousedraw_func32 = tss_ptr->tss_ecx;
  496.       mousedraw_active = 0;
  497.       msdrawfun = (mousedraw_func32 != 0L) ? mousedraw_hook : NULL;
  498.       if(use_DPMI) {
  499.         if(tss_ptr->tss_edx != 0x12345678L) return(0);    /* make sure V1.03 or more */
  500.         mousedraw_callback = (FFUNC)mousedraw_func32;
  501.       }
  502.       event_queue = EventQueueInit(queuesize, MSDRAW_STACK, msdrawfun);
  503.       if(event_queue != NULL) {
  504.         tss_ptr->tss_ebx =
  505.           (((word32)FP_SEG(event_queue)) << 4) +
  506.           ((word32)FP_OFF(event_queue)) +
  507.           0xe0000000L;
  508.         tss_ptr->tss_ecx =
  509.           (((word32)FP_SEG(&mousedraw_contaddr)) << 4) +
  510.           ((word32)FP_OFF(&mousedraw_contaddr)) +
  511.           0xe0000000L;
  512.         tss_ptr->tss_edx =
  513.           (((word32)FP_SEG(&mousedraw_active)) << 4) +
  514.           ((word32)FP_OFF(&mousedraw_active)) +
  515.           0xe0000000L;
  516.       }
  517.       else tss_ptr->tss_ebx = 0L;
  518.     }
  519.     tss_ptr->tss_eax = 0x0ff0;              /* acknowledge event handling */
  520.     return(0);
  521.   }
  522.   if (*((unsigned far *)0x000000CEL) == 0)
  523.     return 0;
  524.   r.r_ax = (word16)(tss_ptr->tss_eax);
  525.   r.r_bx = (word16)(tss_ptr->tss_ebx);
  526.   r.r_cx = (word16)(tss_ptr->tss_ecx);
  527.   r.r_dx = (word16)(tss_ptr->tss_edx);
  528.   intr(0x33, &r);
  529.   tss_ptr->tss_eax = r.r_ax;
  530.   tss_ptr->tss_ebx = r.r_bx;
  531.   tss_ptr->tss_ecx = r.r_cx;
  532.   tss_ptr->tss_edx = r.r_dx;
  533.   return 0;
  534. }
  535.  
  536. /*1.07 TSS last_tss; */
  537.  
  538. i_21(void)
  539. {
  540.   word32 v, trans_total, countleft;
  541.   int i, c, ah, tchar, trans_count;
  542.   char *cp;
  543.   tss2reg(&r);
  544.   ah = ((word16)(tss_ptr->tss_eax) >> 8) & 0xff;
  545.  
  546.   if (ah & 0x80) switch (ah)
  547.   {
  548.     case 0xfe:
  549.       return external_debugger_handler();
  550.     case 0xff:
  551.       return turbo_assist();
  552.     default:
  553.       return 1;
  554.   }
  555.   else switch (ah)
  556.   {
  557.     case 1: /* read with echo */
  558.     case 2: /* con output */
  559.     case 3: /* aux input */
  560.     case 4: /* aux output */
  561.     case 5: /* prn output */
  562.     case 6: /* direct con i/o */
  563.     case 7: /* direct con input */
  564.     case 8: /* kbd read */
  565.     case 0x0b: /* kbd status */
  566.     case 0x0d: /* reset disk */
  567.     case 0x0e: /* select disk */
  568.     case 0x18: /* return al=0 */
  569.     case 0x19: /* get disk */
  570.     case 0x1d: /* return al=0 */
  571.     case 0x1e: /* return al=0 */
  572.     case 0x20: /* return al=0 */
  573.     case 0x2a: /* get date */
  574.     case 0x2b: /* set date */
  575.     case 0x2c: /* get time */
  576.     case 0x2d: /* set time */
  577.     case 0x2e: /* (re)set verify flag */
  578.     case 0x30: /* get version */
  579.     case 0x36: /* get disk free space */
  580.     case 0x37: /* get/set switch char */
  581.     case 0x42: /* seek */
  582.     case 0x4d: /* get return code */
  583.     case 0x54: /* get verify flag */
  584.     case 0x57: /* get/set file time stamp */
  585.     case 0x58: /* get/set UMB link state */
  586.     case 0x66: /* get/set global code page */
  587.     case 0x67: /* set handle count */
  588.     case 0x68: /* commit (flush and update directory) */
  589.       intr(0x21, &r);
  590.       reg2tss(&r);
  591.       return 0;
  592.     case 0x38: /* get country info */
  593.       r.r_ds = _DS;
  594.       r.r_dx = FP_OFF(transfer_buffer);
  595.       intr(0x21, &r);
  596.       if (r.r_flags & 1) 
  597.       {
  598.         tss_ptr->tss_eflags |= 1;
  599.         tss_ptr->tss_eax = r.r_ax;
  600.         return 0;
  601.       }
  602.       memput(tss_ptr->tss_edx + ARENA, transfer_buffer, 34);
  603.       return 0;
  604.     case 0x33: /* ^C checking and more */
  605.       switch (r.r_ax & 0xff) 
  606.       {
  607.       case 0x01: /* set ^C */
  608.       case 0x02: /* set extended ^C */
  609.     ctrl_c_causes_break = r.r_dx & 0xff;
  610.     /* fall through */
  611.       case 0x00: /* get ^C */
  612.       case 0x05: /* get boot drive */
  613.       case 0x06: /* get true dos version */
  614.     intr(0x21, &r);
  615.     reg2tss(&r);
  616.     return 0;
  617.       default:
  618.     return 1;
  619.       }
  620.     case 0x3e: /* close */
  621.       if (using_external_debugger && r.r_bx < 2)
  622.         return 0;
  623.       if (r.r_bx == 1)
  624.         redir_1_mono = redir_1_2 = 0;
  625.       if (r.r_bx == 2)
  626.         redir_2_mono = redir_2_1 = 0;
  627.       intr(0x21, &r);
  628.       reg2tss(&r);
  629.       return 0;
  630.     case 9: /* print string */
  631.     case 0x39: /* mkdir */
  632.     case 0x3a: /* rmdir */
  633.     case 0x3b: /* chdir */
  634.     case 0x41: /* unlink (delete) */
  635.     case 0x43: /* chmod */
  636.       if (ah == 9)
  637.         tchar = '$';
  638.       else
  639.         tchar = 0;
  640.       v = tss_ptr->tss_edx + ARENA;
  641.       CHECK_SEGFAULT(v);
  642.       retrieve_string(v, transfer_buffer, tchar);
  643.       r.r_dx = FP_OFF(transfer_buffer);
  644.       r.r_ds = _DS;
  645.       intr(0x21, &r);
  646.       reg2tss(&r);
  647.       return 0;
  648.     case 0x3c: /* creat (rewrite) */
  649.       v = tss_ptr->tss_edx + ARENA;
  650.       CHECK_SEGFAULT(v);
  651.       retrieve_string(v, transfer_buffer, 0);
  652.       i = _creat(transfer_buffer, (int)(tss_ptr->tss_ecx));
  653.       if (i < 0)
  654.       {
  655.         tss_ptr->tss_eax = errno;
  656.         tss_ptr->tss_eflags |= 1;
  657.       }
  658.       else
  659.       {
  660.         tss_ptr->tss_eax = i;
  661.         tss_ptr->tss_eflags &= ~1;
  662.       }
  663.       return 0;
  664.     case 0x3d: /* open */
  665.       v = tss_ptr->tss_edx + ARENA;
  666.       CHECK_SEGFAULT(v)
  667.       retrieve_string(v, transfer_buffer, 0);
  668.       i = (word16)(tss_ptr->tss_eax) & 0xf0;
  669.       if (tss_ptr->tss_eax & O_WRONLY) i &= 1;
  670.       if (tss_ptr->tss_eax & O_RDWR) i &= 2;
  671.       i = _open(transfer_buffer, i);
  672.       if (i < 0)
  673.       {
  674.         tss_ptr->tss_eax = errno;
  675.         tss_ptr->tss_eflags |= 1;
  676.       }
  677.       else
  678.       {
  679.         tss_ptr->tss_eax = i;
  680.         tss_ptr->tss_eflags &= ~1;
  681.       }
  682.       return 0;
  683.     case 0x1a: /* set dta */
  684.       user_dta = tss_ptr->tss_edx;
  685.       setdta((char far *)transfer_buffer);
  686.       return 0;
  687.     case 0x2f: /* get dta */
  688.       tss_ptr->tss_ebx = user_dta;
  689.       return 0;
  690.     case 0x56: /* rename/move */
  691.       v = tss_ptr->tss_edx + ARENA;
  692.       CHECK_SEGFAULT(v)
  693.       retrieve_string(v, transfer_buffer, 0);
  694.       i = strlen(transfer_buffer) + 1;
  695.       r.r_dx = FP_OFF(transfer_buffer);
  696.       r.r_ds = _DS;
  697.       v = tss_ptr->tss_edi + ARENA;
  698.       retrieve_string(v, transfer_buffer+i, 0);
  699.       r.r_di = FP_OFF(transfer_buffer)+i;
  700.       r.r_es = _DS;
  701.       intr(0x21, &r);
  702.       tss_ptr->tss_eax = r.r_ax;
  703.       tss_ptr->tss_eflags = flmerge(r.r_flags, tss_ptr->tss_eflags);
  704.       return 0;
  705.     case 0x3f: /* read */
  706.       if (!tss_ptr->tss_edx) {
  707.         fprintf(stderr, "This image has a buggy read.s module.  Run DPMIFIX on it and try again.\n");
  708.         return 1;
  709.       }
  710.       if (tss_ptr->tss_edx == transfer_linear)
  711.       {
  712.         i = read(r.r_bx, transfer_buffer, r.r_cx);
  713.         if (i<0)
  714.         {
  715.           tss_ptr->tss_eflags |= 1; /* carry */
  716.           tss_ptr->tss_eax = _doserrno;
  717.         }
  718.         else
  719.         {
  720.           tss_ptr->tss_eflags &= ~1;
  721.           tss_ptr->tss_eax = i;
  722.         }
  723.         return 0;
  724.       }
  725.       trans_total = 0;
  726.       countleft = tss_ptr->tss_ecx;
  727.       v = tss_ptr->tss_edx;
  728.       CHECK_SEGFAULT(v+ARENA)
  729.       while (countleft > 0)
  730.       {
  731.         trans_count = (word16)((countleft <= 4096) ? countleft : 4096);
  732.         i = read(r.r_bx, transfer_buffer, trans_count);
  733.         if (i < 0)
  734.         {
  735.           tss_ptr->tss_eflags |= 1; /* carry */
  736.           tss_ptr->tss_eax = _doserrno;
  737.           return 0;
  738.         }
  739.         memput(v+ARENA, transfer_buffer, i);
  740.         trans_total += i;
  741.         v += i;
  742.         countleft -= i;
  743.         if (isatty(r.r_bx) && (i<trans_count))
  744.           break; /* they're line buffered */
  745.         if (i == 0)
  746.           break;
  747.       }
  748.       tss_ptr->tss_eax = trans_total;
  749.       tss_ptr->tss_eflags &= ~1;
  750.       return 0;
  751.     case 0x40: /* write */
  752.       if (tss_ptr->tss_edx == transfer_linear)
  753.       {
  754.         if ((r.r_bx == 1) && redir_1_mono)
  755.           i = mono_write(transfer_buffer, r.r_cx);
  756.         else if ((r.r_bx == 2) && redir_2_mono)
  757.           i = mono_write(transfer_buffer, r.r_cx);
  758.         else
  759.         {
  760.           int fd = r.r_bx;
  761.           if ((r.r_bx == 2) && redir_2_1)
  762.             fd = 1;
  763.           else if ((r.r_bx == 1) && redir_1_2)
  764.             fd = 2;
  765.           if (r.r_cx == 0) /* for ftruncate */
  766.             i = _write(fd, transfer_buffer, r.r_cx);
  767.           else
  768.             i = write(fd, transfer_buffer, r.r_cx);
  769.         }
  770.         if (i<0)
  771.         {
  772.           tss_ptr->tss_eflags |= 1; /* carry */
  773.           tss_ptr->tss_eax = _doserrno;
  774.         }
  775.         else
  776.         {
  777.           tss_ptr->tss_eflags &= ~1;
  778.           tss_ptr->tss_eax = i;
  779.         }
  780.         return 0;
  781.       }
  782.       trans_total = 0;
  783.       countleft = tss_ptr->tss_ecx;
  784.       if (countleft == 0)
  785.       {
  786.         r.r_ax = 0x4000;
  787.         r.r_cx = 0;
  788.         intr(0x21,&r);
  789.         tss_ptr->tss_eax = 0;
  790.         tss_ptr->tss_eflags &= ~1;
  791.         return 0;
  792.       }
  793.       v = tss_ptr->tss_edx;
  794.       CHECK_SEGFAULT(v+ARENA);
  795.       r.r_dx = (int)transfer_buffer;
  796.       while (countleft > 0)
  797.       {
  798.         trans_count = (word16)((countleft <= 4096) ? countleft : 4096);
  799.         memget(v+ARENA, transfer_buffer, trans_count);
  800.         if ((r.r_bx == 1) && redir_1_mono)
  801.           i = mono_write(transfer_buffer, trans_count);
  802.         else if ((r.r_bx == 2) && redir_2_mono)
  803.           i = mono_write(transfer_buffer, trans_count);
  804.         else
  805.         {
  806.           int fd = r.r_bx;
  807.           if ((r.r_bx == 2) && redir_2_1)
  808.             fd = 1;
  809.           else if ((r.r_bx == 1) && redir_1_2)
  810.             fd = 2;
  811.           i = write(fd, transfer_buffer, trans_count);
  812.           if (in_graphics_mode && (fd < 3))
  813.           {
  814.             word32 far *p = graphics_pt;
  815.             for (c = 0; c < 256; c++)
  816.               *p++ &= ~PT_P;
  817.           }
  818.         }
  819.         if (i<0) /* carry */
  820.         {
  821.           tss_ptr->tss_eflags |= 1; /* carry */
  822.           tss_ptr->tss_eax = _doserrno;
  823.           return 0;
  824.         }
  825.         trans_total += i;
  826.         v += i;
  827.         countleft -= i;
  828.         if (i < trans_count)
  829.           break;
  830.       }
  831.       tss_ptr->tss_eax = trans_total;
  832.       tss_ptr->tss_eflags &= ~1;
  833.       return 0;
  834.     case 0x44: /* ioctl */
  835.       return i_21_44();
  836.     case 0x45: /* dup */
  837.       i = r.r_bx;
  838.       intr(0x21, &r);
  839.       if (!(r.r_flags & 1))
  840.         _openfd[r.r_ax] = i;
  841.       reg2tss(&r);
  842.       return 0;
  843.     case 0x46: /* dup2 */
  844.       i = r.r_bx;
  845.       c = r.r_cx;
  846.       intr(0x21, &r);
  847.       if (!(r.r_flags & 1))
  848.         _openfd[c] = i;
  849.       reg2tss(&r);
  850.       return 0;
  851.     case 0x4e: /* find first */
  852.       CHECK_SEGFAULT(user_dta+ARENA);
  853.       v = tss_ptr->tss_edx + ARENA;
  854.       CHECK_SEGFAULT(v);
  855.       retrieve_string(v, transfer_buffer+43, 0);
  856.       r.r_dx = FP_OFF(transfer_buffer+43);
  857.       r.r_ds = _DS;
  858.       intr(0x21, &r);
  859.       reg2tss(&r);
  860.       for (i=20; i>=0; i--)
  861.         transfer_buffer[i+28] = transfer_buffer[i+26];
  862.       transfer_buffer[32+13] = 0; /* asciiz termination */
  863.       memput(user_dta+ARENA, transfer_buffer, 48);
  864.       return 0;
  865.     case 0x4f: /* find next */
  866.       CHECK_SEGFAULT(user_dta+ARENA);
  867.       memget(user_dta+ARENA, transfer_buffer, 48);
  868.       for (i=0; i<=20; i++)
  869.         transfer_buffer[i+26] = transfer_buffer[i+28];
  870.       intr(0x21, &r);
  871.       reg2tss(&r);
  872.       for (i=20; i>=0; i--)
  873.         transfer_buffer[i+28] = transfer_buffer[i+26];
  874.       transfer_buffer[32+13] = 0; /* asciiz termination */
  875.       memput(user_dta+ARENA, transfer_buffer, 48);
  876.       return 0;
  877.     case 0x47: /* getwd */
  878.       getcurdir((int)(tss_ptr->tss_edx & 0xff), transfer_buffer);
  879.       for (cp=transfer_buffer; *cp; cp++)
  880.       {
  881.         if (*cp == '\\') *cp = '/';
  882.         *cp = tolower(*cp);
  883.       }
  884.       memput(tss_ptr->tss_esi+ARENA, transfer_buffer, strlen(transfer_buffer)+1);
  885.       tss_ptr->tss_eax = (unsigned)r.r_ax;
  886.       tss_ptr->tss_eflags &= ~1;
  887.       return 0;
  888.     case 0x4a: /* sbrk/brk -- NOT ORGINAL MEANING */
  889.       if (tss_ptr->tss_eax & 0xff)
  890.         tss_ptr->tss_eax = paging_sbrk(tss_ptr->tss_ebx);
  891.       else
  892.         tss_ptr->tss_eax = paging_brk(tss_ptr->tss_ebx);
  893.       return 0;
  894.     case 0x4c: /* exit */
  895.       if (using_external_debugger)
  896.         return 1;
  897.       else
  898.         exit((word8)(tss_ptr->tss_eax));
  899.     default:
  900.       return 1;
  901.   }
  902. }
  903.  
  904. static int reg2gate(word32 r)
  905. {
  906.   int g = (int)(r & 0xff);
  907.   if (g >= 0x08 && g <= 0x0f)
  908.     g = g - 0x08 + hard_master_lo;
  909.   else if (g >= 0x70 && g <= 0x77)
  910.     g = g - 0x70 + hard_slave_lo;
  911.   return g;
  912. }
  913.  
  914. static int dpmisim_is_exec = 0;
  915.  
  916. int i_31(void)
  917. {
  918.   int gate, i;
  919.   word16 far *fptr;
  920.   word16 dpmisim_spare_stack[128];
  921.   union REGS r;
  922.   struct SREGS s;
  923.   switch ((word16)(tss_ptr->tss_eax))
  924.   {
  925.     case 0x0100:
  926.       r.h.ah = 0x48;
  927.       r.x.bx = (word16)tss_ptr->tss_ebx;
  928.       int86(0x21, &r, &r);
  929.       if ((r.x.flags & 1) && ((word16)tss_ptr->tss_ebx != 0xffff))
  930.       {
  931.         valloc_shrink_rmem(((word16)tss_ptr->tss_ebx)/256 + 1);
  932.         r.h.ah = 0x48;
  933.         r.x.bx = (word16)tss_ptr->tss_ebx;
  934.         int86(0x21, &r, &r);
  935. /*        if (r.x.flags & 1)
  936.           printf("biggest after shrinking is %04x\n", r.x.bx); */
  937.       }
  938.       tss_ptr->tss_eflags &= ~1;
  939.       tss_ptr->tss_eflags |= r.x.flags & 1;
  940.       tss_ptr->tss_edx =
  941.       tss_ptr->tss_eax = r.x.ax;
  942.       tss_ptr->tss_ebx = r.x.bx;
  943. /*      printf("allocated %x, %d %x\n", r.x.ax, r.x.flags & 1, r.x.bx); */
  944.       return 0;
  945.  
  946.     case 0x0101:
  947.       r.h.ah = 0x49;
  948.       r.x.bx = (word16)tss_ptr->tss_edx;
  949.       int86(0x21, &r, &r);
  950. /*      printf("released %x, %d %x\n", (word16)tss_ptr->tss_edx, r.x.flags & 1, r.x.ax); */
  951.       return 0;
  952.  
  953.     case 0x0102:
  954.       r.h.ah = 0x4a;
  955.       r.x.bx = (word16)tss_ptr->tss_ebx;
  956.       s.es = (word16)tss_ptr->tss_edx;
  957.       int86x(0x21, &r, &r, &s);
  958.       tss_ptr->tss_eflags &= ~1;
  959.       tss_ptr->tss_eflags |= r.x.flags & 1;
  960.       tss_ptr->tss_eax = r.x.ax;
  961.       tss_ptr->tss_ebx = r.x.bx;
  962.       return 0;
  963.  
  964.     case 0x0200:
  965.       gate = (word8)tss_ptr->tss_ebx;
  966.       tss_ptr->tss_ecx = peek(0, gate*4+2);
  967.       tss_ptr->tss_edx = peek(0, gate*4);
  968.       tss_ptr->tss_eflags &= ~1;
  969.       return 0;
  970.  
  971.     case 0x0201:
  972.       gate = (word8)tss_ptr->tss_ebx;
  973.       disable();
  974.       poke(0, gate*4+2, tss_ptr->tss_ecx);
  975.       poke(0, gate*4, tss_ptr->tss_edx);
  976.       enable();
  977.       tss_ptr->tss_eflags &= ~1;
  978.       return 0;
  979.  
  980.     case 0x0204:
  981.       gate = reg2gate(tss_ptr->tss_ebx);
  982.       tss_ptr->tss_ecx = idt[gate].selector;
  983.       tss_ptr->tss_edx = idt[gate].offset0 | (idt[gate].offset1 << 16);
  984.       tss_ptr->tss_eflags &= ~1;
  985.       return 0;
  986.  
  987.     case 0x0205:
  988.       gate = reg2gate(tss_ptr->tss_ebx);
  989.       idt[gate].selector = (word16)(tss_ptr->tss_ecx);
  990.       idt[gate].offset0 = (word16)(tss_ptr->tss_edx);
  991.       idt[gate].offset1 = (word16)(tss_ptr->tss_edx >> 16);
  992.       idt[gate].stype = 0x8e00;
  993.       tss_ptr->tss_eflags &= ~1;
  994.       return 0;
  995.  
  996.     case 0x0300:
  997.     case 0x0301:
  998.     case 0x0302:
  999.       CHECK_SEGFAULT(tss_ptr->tss_edi + ARENA);
  1000.       if (tss_ptr->tss_ecx)
  1001.       {
  1002.         tss_ptr->tss_eax = 0x8021;
  1003.         tss_ptr->tss_eflags |= 1;
  1004.         return 0;
  1005.       }
  1006.       memget(tss_ptr->tss_edi + ARENA, dpmisim_regs, 50);
  1007.  
  1008.       if (dpmisim_regs[24] == 0)
  1009.       {
  1010.         dpmisim_regs[24] = _SS;
  1011.         dpmisim_regs[23] = (word16)(dpmisim_spare_stack) + sizeof(dpmisim_spare_stack);
  1012.       }
  1013.       if ((word16)tss_ptr->tss_eax != 0x0301)
  1014.       {
  1015.         dpmisim_regs[23] -= 2;    /* fake pushing flags on stack */
  1016.         fptr = MK_FP(dpmisim_regs[24], dpmisim_regs[23]);
  1017.         *fptr = dpmisim_regs[16];
  1018.       }
  1019.  
  1020.       if ((word16)tss_ptr->tss_eax == 0x0300)
  1021.       {
  1022.         dpmisim_regs[21] = peek(0, (word8)tss_ptr->tss_ebx * 4);
  1023.         dpmisim_regs[22] = peek(0, (word8)tss_ptr->tss_ebx * 4 + 2);
  1024.       }
  1025.  
  1026.       if (dpmisim_is_exec)
  1027.       {
  1028.         word32 our_interrupt_table[256];
  1029.         page_out_everything();
  1030.         movedata(0, 0, FP_SEG(our_interrupt_table), FP_OFF(our_interrupt_table), 256*4);
  1031.         uninit_controllers();
  1032.         dpmisim();
  1033.         init_controllers();
  1034.         movedata(FP_SEG(our_interrupt_table), FP_OFF(our_interrupt_table), 0, 0, 256*4);
  1035.        page_in_everything();
  1036.       }
  1037.       else
  1038.         dpmisim();
  1039.  
  1040.       memput(tss_ptr->tss_edi + ARENA, dpmisim_regs, 50);
  1041.       tss_ptr->tss_eflags &= ~1;
  1042.       return 0;
  1043.  
  1044.     case 0x0303:
  1045.       CHECK_SEGFAULT(tss_ptr->tss_edi + ARENA);
  1046.       for (i=0; i<16; i++)
  1047.         if (dpmisim_rmcb[i].cb_address == 0)
  1048.           break;
  1049.       if (i == 16)
  1050.       {
  1051.         tss_ptr->tss_eflags |= 1;
  1052.         tss_ptr->tss_eax = 0x8015;
  1053.         return 0;
  1054.       }
  1055.       dpmisim_rmcb[i].cb_address = tss_ptr->tss_esi;
  1056.       dpmisim_rmcb[i].reg_ptr = tss_ptr->tss_edi;
  1057.       tss_ptr->tss_eflags &= ~1;
  1058.       tss_ptr->tss_ecx = _CS;
  1059.       tss_ptr->tss_edx = (word16)dpmisim_rmcb0 + i * ((word16)dpmisim_rmcb1 - (word16)dpmisim_rmcb0);
  1060.       return 0;
  1061.  
  1062.     case 0x0304:
  1063.       if ((word16)tss_ptr->tss_ecx == _CS)
  1064.         for (i=0; i<16; i++)
  1065.           if ((word16)tss_ptr->tss_edx == (word16)dpmisim_rmcb0 + i * ((word16)dpmisim_rmcb1 - (word16)dpmisim_rmcb0))
  1066.           {
  1067.             dpmisim_rmcb[i].cb_address = 0;
  1068.             tss_ptr->tss_eflags &= ~1;
  1069.             return 0;
  1070.           }
  1071.       tss_ptr->tss_eflags |= 1;
  1072.       tss_ptr->tss_eax = 0x8024;
  1073.       return 0;
  1074.       
  1075.     case 0x0500:
  1076.       CHECK_SEGFAULT(tss_ptr->tss_edi + ARENA);
  1077.       memset(transfer_buffer, 0xff, 48);
  1078.       ((word32 *)transfer_buffer)[8] = dalloc_max_size();
  1079.       ((word32 *)transfer_buffer)[4] =
  1080.       ((word32 *)transfer_buffer)[6] = valloc_max_size();
  1081.       ((word32 *)transfer_buffer)[2] =
  1082.       ((word32 *)transfer_buffer)[5] = valloc_max_size() - valloc_used();
  1083.       ((word32 *)transfer_buffer)[1] = 
  1084.         ((word32 *)transfer_buffer)[5] + ((word32 *)transfer_buffer)[8] - dalloc_used();
  1085.       ((word32 *)transfer_buffer)[0] = ((word32 *)transfer_buffer)[1] * 4096L;
  1086.       memput(tss_ptr->tss_edi + ARENA, transfer_buffer, 48);
  1087.       tss_ptr->tss_eflags &= ~1;
  1088.       return 0;
  1089.  
  1090.     default: /* mark as unsupported */
  1091.       tss_ptr->tss_eflags |= 1;
  1092.       tss_ptr->tss_eax = 0x8001;
  1093.       return 0;
  1094.   }
  1095. }
  1096.  
  1097. struct time32 {
  1098.   word32 secs;
  1099.   word32 usecs;
  1100. };
  1101.  
  1102. struct tz32 {
  1103.   word32 offset;
  1104.   word32 dst;
  1105. };
  1106.  
  1107. struct  stat32 {
  1108.         short st_dev;
  1109.         short st_ino;
  1110.         short st_mode;
  1111.         short st_nlink;
  1112.         short st_uid;
  1113.         short st_gid;
  1114.         short st_rdev;
  1115.         short st_align_for_word32;
  1116.         long  st_size;
  1117.         long  st_atime;
  1118.         long  st_mtime;
  1119.         long  st_ctime;
  1120.         long  st_blksize;
  1121. };
  1122.  
  1123. static int dev_count=1;
  1124.  
  1125. turbo_assist(void)
  1126. {
  1127.   word32 p1, p2, r;
  1128.   struct time32 time32;
  1129.   struct tz32 tz32;
  1130.   struct stat32 statbuf32;
  1131.   struct stat statbuf;
  1132.   int i;
  1133.   char buf[128], *bp;
  1134.   word32 our_interrupt_table[256];
  1135.  
  1136.   p1 = tss_ptr->tss_ebx;
  1137.   p2 = tss_ptr->tss_ecx;
  1138.   switch ((word8)(tss_ptr->tss_eax))
  1139.   {
  1140.     case 1: /* creat */
  1141.       retrieve_string(p1+ARENA, buf, 0);
  1142.       r = creat(buf, S_IREAD | S_IWRITE);
  1143.       break;
  1144.  
  1145.     case 2: /* open */
  1146.       retrieve_string(p1+ARENA, buf, 0);
  1147.       r = open(buf, (int)p2, S_IREAD | S_IWRITE);
  1148.       break;
  1149.  
  1150.     case 3: /* fstat */
  1151.       memset(&statbuf, 0, sizeof(statbuf));
  1152.       r = fstat((int)p1, &statbuf);
  1153.       statbuf32.st_dev = dev_count++;
  1154.       statbuf32.st_ino = statbuf.st_ino;
  1155.       statbuf32.st_mode = statbuf.st_mode;
  1156.       statbuf32.st_nlink = statbuf.st_nlink;
  1157.       statbuf32.st_uid = 42;
  1158.       statbuf32.st_gid = 42;
  1159.       statbuf32.st_rdev = statbuf.st_rdev;
  1160.       statbuf32.st_size = statbuf.st_size;
  1161.       statbuf32.st_atime = statbuf.st_atime;
  1162.       statbuf32.st_mtime = statbuf.st_mtime;
  1163.       statbuf32.st_ctime = statbuf.st_ctime;
  1164.       statbuf32.st_blksize = 512;
  1165.       memput(p2+ARENA, &statbuf32, sizeof(statbuf32));
  1166.       break;
  1167.  
  1168.     case 4: /* gettimeofday */
  1169.       if (p2)
  1170.       {
  1171.         CHECK_SEGFAULT(p2+ARENA);
  1172.         tz32.offset = timezone;
  1173.         tz32.dst = daylight;
  1174.         memput(p2+ARENA, &tz32, sizeof(tz32));
  1175.       }
  1176.       if (p1)
  1177.       {
  1178.         int dh;
  1179.         CHECK_SEGFAULT(p1+ARENA);
  1180.         time((long *)&(time32.secs));
  1181.         _AH = 0x2c;
  1182.         geninterrupt(0x21);
  1183.         dh = _DH;
  1184.         time32.usecs = _DL * 10000L;
  1185.         if (time32.secs % 60 != dh)
  1186.           time32.secs++;
  1187.         memput(p1+ARENA, &time32, sizeof(time32));
  1188.       }
  1189.       r = 0;
  1190.       break;
  1191.  
  1192.     case 5: /* settimeofday */
  1193.       if (p2)
  1194.       {
  1195.         CHECK_SEGFAULT(p2+ARENA);
  1196.         memget(p2+ARENA, &tz32, sizeof(tz32));
  1197.         timezone = tz32.offset;
  1198.         daylight = (int)tz32.dst;
  1199.       }
  1200.       if (p1)
  1201.       {
  1202.         CHECK_SEGFAULT(p1+ARENA);
  1203.         memget(p1+ARENA, &time32, sizeof(time32));
  1204.         stime((long *)&(time32.secs));
  1205.       }
  1206.       r = 0;
  1207.       break;
  1208.  
  1209.     case 6: /* stat */
  1210.       memset(&statbuf, 0, sizeof(statbuf));
  1211.       retrieve_string(p1+ARENA, transfer_buffer, 0);
  1212.       r = unixlike_stat(transfer_buffer, &statbuf);
  1213.       statbuf32.st_dev = dev_count++;
  1214.       statbuf32.st_ino = statbuf.st_ino;
  1215.       statbuf32.st_mode = statbuf.st_mode;
  1216.       statbuf32.st_nlink = statbuf.st_nlink;
  1217.       statbuf32.st_uid = statbuf.st_uid;
  1218.       statbuf32.st_gid = statbuf.st_gid;
  1219.       statbuf32.st_rdev = statbuf.st_rdev;
  1220.       statbuf32.st_size = statbuf.st_size;
  1221.       statbuf32.st_atime = statbuf.st_atime;
  1222.       statbuf32.st_mtime = statbuf.st_mtime;
  1223.       statbuf32.st_ctime = statbuf.st_ctime;
  1224.       statbuf32.st_blksize = 512;
  1225.       memput(p2+ARENA, &statbuf32, sizeof(statbuf32));
  1226.       break;
  1227.  
  1228.     case 7: /* system */
  1229.       retrieve_string(p1+ARENA, transfer_buffer, 0);
  1230.       page_out_everything();
  1231.       movedata(0, 0, FP_SEG(our_interrupt_table), FP_OFF(our_interrupt_table), 256*4);
  1232.       uninit_controllers();
  1233.       sscanf(transfer_buffer, "%s%n", buf, &i);
  1234.       if (strpbrk(transfer_buffer, "<>|") == NULL)
  1235.         r = spawnlp(P_WAIT, buf, buf, transfer_buffer+i, 0);
  1236.       else
  1237.         r = -1;
  1238.       bp = buf+strlen(buf)-4;
  1239.       if (stricmp(bp, ".exe") && stricmp(bp, ".com") && (r & 0x80000000L))
  1240.         r = system(transfer_buffer);
  1241.       init_controllers();
  1242.       movedata(FP_SEG(our_interrupt_table), FP_OFF(our_interrupt_table), 0, 0, 256*4);
  1243.       page_in_everything();
  1244.       break;
  1245.  
  1246.     case 8: /* _setmode() */
  1247.       _BX=(int)p1;
  1248.       _AX=0x4400;
  1249.       geninterrupt(0x21);
  1250.       i = _DX;
  1251.       if (p2 & O_BINARY)
  1252.         i |= 0x20;
  1253.       else
  1254.         i &= ~0x20;
  1255.       _BX=(int)p1;
  1256.       _DX = i;
  1257.       _AX=0x4401;
  1258.       geninterrupt(0x21);
  1259.       r = setmode((int)p1, (int)p2);
  1260.       break;
  1261.  
  1262.     case 9: /* chmod */
  1263.       retrieve_string(p1+ARENA, buf, 0);
  1264.       r = chmod(buf, (int)p2);
  1265.       break;
  1266.  
  1267.     case 10: /* DPMI exec */
  1268.       dpmisim_is_exec = 1;
  1269.       tss_ptr->tss_eax = 0x0300;
  1270.       i_31();
  1271.       dpmisim_is_exec = 0;
  1272.       return 0;
  1273.  
  1274.     default:
  1275.       return 1;
  1276.   }
  1277.   tss_ptr->tss_eflags &= ~1;
  1278.   if (r == -1)
  1279.   {
  1280.     tss_ptr->tss_eflags |= 1;
  1281.     tss_ptr->tss_eax = errno;
  1282.     return 0;
  1283.   }
  1284.   tss_ptr->tss_eax = r;
  1285.   return 0;
  1286. }
  1287.  
  1288. i_21_44(void)
  1289. {
  1290.   switch ((word8)(tss_ptr->tss_eax))
  1291.   {
  1292.     case 0x00:
  1293.     case 0x01:
  1294.     case 0x06:
  1295.     case 0x07:
  1296.     case 0x08:
  1297.     case 0x09:
  1298.     case 0x0a:
  1299.     case 0x0b:
  1300.     case 0x0e:
  1301.     case 0x0f:
  1302.       intr(0x21, &r);
  1303.       tss_ptr->tss_edx = r.r_dx;
  1304.       tss_ptr->tss_eax = r.r_ax;
  1305.       tss_ptr->tss_eflags = flmerge(r.r_flags, tss_ptr->tss_eflags);
  1306.       return 0;
  1307.     default:
  1308.       return 1;
  1309.   }
  1310. }
  1311.